from PIL import Image  # 图片处理模块
import argparse


class I2Char:
    # 最大宽度
    __max_width = 80

    # 最大高度
    __max_height = 80

    # 转换的字符集合，共70个，可自己优化添加，越多越逼真，每个字符对应一种或者几种亮度
    __ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")

    def genCharImage(self, image):
        # 1.通过PiL模块加载一张图片到内存
        im = Image.open(image)
        # 2.设置图片的尺寸
        im = im.resize(self.__getSize(im), Image.NEAREST)
        txt = ""
        # 3.遍历提取图片中每行的像素的 RGB 值，调用 getchar 转成对应的字符
        for i in range(im.size[1]):
            for j in range(im.size[0]):
                # 获取得到坐标 (j,i) 位置的 RGB 像素值（有的时候会包含 alpha 值），
                # 返回的结果是一个元组，例如 (1,2,3) 或者 (1,2,3,0)
                # 4.将所有的像素对应的字符拼接在一起成为一个字符串 txt
                txt += self.__getChar(*im.getpixel((j, i)))
            txt += '\n'
        # 5.返回字符串 txt
        return txt

    # 将256灰度映射到70个字符上
    def __getChar(self, r, g, b, alpha=256):
        # alpha 值为 0 的时候表示图片中该位置为空白
        if alpha == 0:
            return ' '
        length = len(self.__ascii_char)
        # 把RGB色域转换成灰度图 ，使用权重
        gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
        # ascii_char有70个，把256个灰度值分成70组
        unit = (256.0 + 1) / length
        # 当前像素的灰度属于70个组中的哪个组
        return self.__ascii_char[int(gray / unit)]

    # 获取字符画合适尺寸 (保持比例)
    def __getSize(self, im):
        width = im.size[0]
        height = im.size[1]
        if width > height:
            if width > self.__max_width:
                width = self.__max_width
                height = self.__max_width * im.size[1] // im.size[0]
        else:
            if height > self.__max_height:
                height = self.__max_height
                width = self.__max_height * im.size[0] // im.size[1]
        return width, height


def main():
    # 命令行输入参数处理
    parser = argparse.ArgumentParser()
    # 输入文件
    parser.add_argument('file')
    # 获取参数
    args = parser.parse_args()
    # 实列化I2Char类
    i2char_obj = I2Char()
    # 调用I2Char类中的genCharImage，获取字符画字符串
    char_image = i2char_obj.genCharImage(args.file)
    # 输出字符画
    print(char_image)


if __name__ == '__main__':
    ## 实列化I2Char类
    #i2char_obj = I2Char()
    ## 调用I2Char类中的genCharImage，获取字符画字符串
    #i2char_obj.genCharImage(r"C:\Users\Administrator\Downloads\模块一 第二章\素材\7.图片和视频转字符动画\t3.jpeg")
    main()
